<template>
  <!-- 权限管理页面 -->
  <!-- appMain区域 -->
  <div class="departments-container">
    <!-- 内边距区域 -->
    <div class="app-container">
      <!-- 卡片组件(分为头部和身体) -->
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <el-tabs v-model="activeName">
            <!-- name属性 === value -->
            <!-- label === 选项卡标题 -->
            <el-tab-pane label="组织架构" name="first">
              <!-- class="tab-pane"设置左右padding, 把内容往中间挤压 -->
              <!-- 使用 Layout 布局绘制头部区域
                              最外层一行, 2列
                                el-row: type布局模式
                                        justify两端对齐
                                        align交叉轴排列方式(垂直方向居中)
                             -->
              <el-row type="flex" justify="space-between" align="middle" class="department-header">
                <!-- 第一列20份 -->
                <el-col :span="20">
                  <i class="el-icon-s-home" />
                  <span class="company">江苏传智播客教育科技股份有限公司</span>
                </el-col>
                <!-- 第二列4份 -->
                <el-col :span="4">
                  <!-- 在容器范围里, 一行再分2列 -->
                  <el-row type="flex" justify="end">
                    <el-col :span="12">负责人</el-col>
                    <el-col :span="12">
                      <!-- 这个之前在头部导航右侧下拉菜单讲过 -->
                      <el-dropdown>
                        <!-- 下拉菜单文字 -->
                        <span class="el-dropdown-link">
                          操作<i class="el-icon-arrow-down el-icon--right" />
                        </span>
                        <!-- 下拉项 -->
                        <el-dropdown-menu slot="dropdown">
                          <el-dropdown-item @click.native="add('')">添加子部门</el-dropdown-item>
                        </el-dropdown-menu>
                      </el-dropdown>
                    </el-col>
                  </el-row>
                </el-col>
              </el-row>
            </el-tab-pane>
          </el-tabs>
        </div>
        <!-- 树形控件 -->
        <!-- 列表
            只要有嵌套: 8成用的是递归组件(你想要感受下M可以去看layout/sidebar/el-submenu)
            tree已经在里面封装好了,所以我们只要把数据的结构弄成嵌套的,标签自动嵌套
            数组套对象(第一层"对象" -> 第一层节点(每"行"(对象理解为一行) - 最左边无缩进) (节点 -> 一行标签))
            ** 如果有children就证明有缩进嵌套行节点(子节点)
            ** 对象label,当前行的文字
            tree组件主要是 children + label 属性,props是tree的配置项

            知识点1:
            :叫动态属性: 它会把 = 右侧的东西看做表达式(加了冒号右边的就是表达式,不加冒号右边就是字符串)
            表达式: 变量,常量和运算符组成(表达式在原地是有结果的)

            知识点2:
            (标签上直接写属性,但是没有值,此属性接到的默认值true(布尔类型))
            如果非要写要注意字符串还是布尔类型
         -->
        <el-tree class="departments-tree" :data="treeData" node-key="id"
          :expand-on-click-node="false" default-expand-all>
          <!-- 默认插槽  并且使用内部的数据进行自定义模板的渲染, scope.data 所以直接key解构赋值变量也是data(对应数据对象)-->
          <!--
                问题: 前提: 使用插槽技术的时候,想要在插槽具体标签位置,拿到组件内给插槽绑定属性和值?
                答案: v-slot="变量名" (变量名的值: 就会收集slot占位标签身上属性和值形成对象)
                例如: v-slot="scope" scope的值 组件内源码在slot占位标签身上属性名和值 { data: 行数据对象 }
                el-table的时候, 作用域插槽, 那个table里面绑定的属性名 row: 行数据对象

                现在scope变量值 { data: 行数据对象 }
                知识点: v-slot: 可以简化成 #

                还原写法1:
                #default="{ data }" v-slot:default="scope"
                取值时: scope.data.name

                简化1: 把data值结构赋值从scope里快速取出
                v-slot:default="{ data: data}" es6语法key&value相等可以省略key
                v-slot:default="{ data }"

                简化2: v-slot: 省略成#

                具名插槽default(默认) 可以分配给 内slot标签无名的 / 有 default 名字的都可以分配
                不写名字,也能分配给slot标签无名 / 有default名字的都可以分配
                例子: 组件内 <slot></slot> 不写名字默认有一个名字叫 default
                      组件外使用 <template v-slot></template>
                      组件外使用 <template #default></template>
                      都可以但是一般不要给插槽具名default,语义化差

                我的理解 使用插槽的时候只要后面不加 ="" 就是仅仅使用插槽,
                         加了 = 就是接收插槽传出来的值,就是作用域插槽啦
           -->
          <template #default="{ data }">
            <el-row type="flex" justify="space-between" align="middle" style="height: 40px; width: 100%;">
              <!-- 部门名字 -->
              <el-col :span="20">
                <!-- {{data}} -->
                <span>{{ data.name }}</span>
              </el-col>
              <!-- 功能操作区域 -->
              <el-col :span="4">
                <el-row type="flex" justify="end">
                  <!-- 两个内容 -->
                  <el-col>{{ data.manager }}</el-col>
                  <el-col>
                    <!-- 下拉菜单 element -->
                    <el-dropdown>
                      <span> 操作<i class="el-icon-arrow-down" /> </span>
                      <!-- 下拉菜单 -->
                      <el-dropdown-menu slot="dropdown">
                        <el-dropdown-item @click.native="add(data)">添加子部门</el-dropdown-item>
                        <el-dropdown-item @click.native="edit(data)">编辑部门</el-dropdown-item>
                        <el-dropdown-item @click.native="del(data)" v-if="data && !data.children">删除部门
                        </el-dropdown-item>
                      </el-dropdown-menu>
                    </el-dropdown>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-tree>
      </el-card>
    </div>
    <!-- Dialog弹出层组件 -->
    <!-- .sync修饰符原理还是子父组件通信只是简化了写法 -->
    <Dialog ref="DepartmentDialog" :departmentDialog.sync="departmentDialog" :staffList="staff"
      @addOrUpdateDepartemtFn="addOrUpdateDepartemtFn"
      :originList="originList"
      :isEdit="isEdit"
      :selectedPid="selectedPid"
      ></Dialog>
  </div>
</template>
<script>
  import {
    getDepartmentListAPI,
    getEmployeeSimpleListAPI,
    addDepartmentAPI,
    useIdSelecteDepartmentInfoAPI,
    useIdUpdateDepartmentInfoAPI,
    useIdDeleteDepartmentInfoAPI
  } from '@/api'
  import {
    transTree
  } from '@/utils/handleTreeData'
  import Dialog from './component/departmentDialog.vue'
  export default {
    name: 'Departments',
    data() {
      return {
        activeName: 'first',
        // 树形控件数据对象,要显示什么数据靠这里面的数据对象
        treeData: [],
        staff: [], // 员工列表
        departmentDialog: false, // 弹出层显示 / 隐藏
        selectedPid: '', // 当前选中的弹出层的pid(实际放的是当前父的id)
        isEdit: false, // 是否为编辑模式(因为新增编辑共用同一个弹出层,需要一个变量值区分)
        // defaultProps: { tree 组件默认展示内容
        //   children: 'children', //children属性对应值,要对应数据对象哪个字段(来决定行节点是否有嵌套的子节点数据)
        //   label: 'label' // label属性对应值,要对应数据对象里哪个字段(此对象字段值,决定节点行标签显示的中文)
        // }
        originList: [], // 子组件重组校验数组
      }
    },
    created() {
      this.getDepartmentListFn()
      this.getEmployeeSimpleListFn()
    },
    methods: {
      // 获取部门信息
      async getDepartmentListFn() {
        const res = await getDepartmentListAPI()
        // 自定义重组数组,传递给子组件做字段校验(需求)
        this.originList = res.data.depts.map(item => (
                {
                    id: item.id,
                    code: item.code,
                    name: item.name,
                    pid: item.pid // 下面使用
                }
            ))
        this.treeData = transTree(res.data.depts, '') // 扁平数组 -> 嵌套数组
      },
      // 获取员工基本信息(部门负责人用)
      async getEmployeeSimpleListFn() {
        const res = await getEmployeeSimpleListAPI()
        this.staff = res.data
        // console.log(res)
      },
      // 新增/编辑组织结构信息
      // 添加子部门 -> 确定添加方法
      // 编辑子部门 -> 确定也走这里
      // formobj 是子传出来的值
      async addOrUpdateDepartemtFn(formobj) {
        /*
          formobj 有7对key+value
          原因: 编辑的时候,把子组件form变量重新赋予了一个新对象(后台查询到的数据对象)
        */
        if (this.isEdit) { // 修改部门
           await useIdUpdateDepartmentInfoAPI(formobj)
          this.$message('修改成功')
        } else { // 新增部门
          /*这里实则是发送父的id到后台而不是父的pid,
            如果父的pid,父一级的pid为"",那添加部门永远为添加一级部门
            但是发送父的id当做当前子的pid,即可形成绑定嵌套关系
            因为子的pid和父的id形成一个关联,子的id不能和父的id相同
          */
          // formobj 默认接收4对key+value
          // 当点击修改后,formobj就会变为7对key+value,但是新增只用到其中的4对k&v,多余的参数传递给后台也无所谓,后台是不会接收的
          formobj.pid = this.selectedPid // 整理合并发送参数数据字段
          await addDepartmentAPI(formobj)
          this.$message('新增部门成功')
        }
        this.getDepartmentListFn() // 刷新页面
      },
      // 正文部分-右侧的添加子部门
      // 头部 -> 添加子部门 data是undefined(一级部门pid='')
      // 列表 -> 添加子部门 data是一行对应的部门对象 -> treeData里数据 （子部门pid=父id)
      add(data) { // data 当前 row 对象
        // data必须传参,不传默认会注入一个原生事件对象！！！
        if (!data) {
          this.selectedPid = '' // 添加一级部门
        } else {
          // 添加二级部门
          this.selectedPid = data.id // 这里赋值因为新增接口需要用到该参数
        }
        this.departmentDialog = true // 弹窗显示
        this.isEdit = false // 默认为添加模式
      },
      // 编辑子部分
      async edit(data) {
        this.selectedPid = data.id // 为做部门编码校验(编辑状态)而赋值
        this.isEdit = true // 改为修改模式
        // 查当前部门的详细信息,准备进行数据回显
        const res = await useIdSelecteDepartmentInfoAPI(data.id)
        this.departmentDialog = true // 弹窗显示
        // 直接访问子组件内 data 的变量,进行赋值子组件form表单,完成数据驱动视图回显操作
        setTimeout(() => {
          this.$refs.DepartmentDialog.form = res.data
        },0)
      },
      // 删除部分
      del(data) {
        this.$confirm('确认删除?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(async () => {
          try {
            await useIdDeleteDepartmentInfoAPI(data.id)
            this.getDepartmentListFn() // 刷新页面
            this.$message('删除成功');
          } catch (e) {
            console.log(e)
            this.$message(e, 'error');
          }
        }).catch(() => {
          this.$message('已取消删除', 'info');
        });
      }
    },
    computed: {},
    components: {
      Dialog
    }
  }
</script>
<style lang="scss" scoped>
  .departments-tree {
    margin: 12px 0px;
  }

  .box-card {
    padding: 10px 30px;
  }

  .tab-pane {
    padding: 20px 80px;

    .company {
      margin-left: 12px;
      font-weight: bold;
      font-size: 14px;
    }

    .department-header {
      height: 50px;
      display: flex;
      align-items: center;
      border-bottom: 1px solid #ccc;
    }
  }
</style>

<style scoped lang="scss">
  // 树样式
  .el-tree {
    ::v-deep .el-tree-node {
      position: relative;
      padding-left: 16px; // 缩进量
    }

    ::v-deep .el-tree-node__children {
      padding-left: 16px; // 缩进量
    }

    // 竖线
    ::v-deep .el-tree-node::before {
      content: "";
      height: 100%;
      width: 1px;
      position: absolute;
      left: -3px;
      top: -26px;
      border-width: 1px;
      border-left: 1px dashed #ccc;
    }

    // 当前层最后⼀个节点的竖线⾼度固定
    ::v-deep .el-tree-node:last-child::before {
      height: 38px; // 可以⾃⼰调节到合适数值
    }

    // 横线
    ::v-deep .el-tree-node::after {
      content: "";
      width: 24px;
      height: 20px;
      position: absolute;
      left: -3px;
      top: 12px;
      border-width: 1px;
      border-top: 1px dashed #ccc;
    }

    // 去掉最顶层的虚线，放最下⾯样式才不会被上⾯的覆盖了
    // &> ::v-deep .el-tree-node::after {
    //   border-top: none;
    // }

    // &> ::v-deep .el-tree-node::before {
    //   border-left: none;
    // }

    // 展开关闭的icon
    // ::v-deep .el-tree-node__expand-icon {
    //   font-size: 16px;

    //   // 叶⼦节点（⽆⼦节点）
    //   ::v-deep &.is-leaf {
    //     color: transparent;
    //     // display: none; // 也可以去掉
    //   }
    // }
  }
</style>
